﻿using movie.tool.library.binding;
using movie.tool.module.encode;
using movie.tool.module.film.model;
using movie.tool.module.film.service;
using movie.tool.module.http;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Linq;
using movie.tool.module.importer.ui;
using movie.tool.module.login;

namespace movie.tool.module.film.ui
{
    public class MovieListFilter : NotifyPropertyChanged
    {
        private string name;
        public string Name
        {
            get => name;
            set
            {
                name = value;
                SendPropertyChanged(nameof(Name));
            }
        }
    }
    public class PagingData : NotifyPropertyChanged
    {
        private int current;
        private int pages;
        private int size;
        private int total;
        public int Current
        {
            get { return current; }
            set
            {
                current = value;
                SendPropertyChanged(nameof(Current));
            }
        }
        public int Pages
        {
            get { return pages; }
            set
            {
                pages = value;
                SendPropertyChanged(nameof(Pages));
            }
        }
        public int Size
        {
            get { return size; }
            set
            {
                size = value;
                SendPropertyChanged(nameof(Size));
            }
        }
        public int Total
        {
            get { return total; }
            set
            {
                total = value;
                SendPropertyChanged(nameof(Total));
            }
        }
        public List<Movie> Records { get; set; }
    }
    /// <summary>
    /// MovieListPage.xaml 的交互逻辑
    /// </summary>
    public partial class MovieListPage : Page,INotifyPropertyChanged
    {
        private ObservableCollection<Movie> movieList;
        public ObservableCollection<Movie> MovieList {
            get => movieList;
            private set
            {
                movieList = value;
                SendPropertyChanged(nameof(MovieList));
            }
        }
        private Movie selectedItem;
        public Movie SelectedItem
        {
            get => selectedItem;
            set
            {
                selectedItem = value;
                SendPropertyChanged(nameof(SelectedItem));
            }
        }
        private BusyInfo busyInfo;
        public BusyInfo BusyInfo
        {
            get => busyInfo;
            set
            {
                busyInfo = value;
                SendPropertyChanged(nameof(BusyInfo));
            }
        }
        public PagingData PagingData { get; private set; }
        public MovieListFilter Filters { get; private set; }
        public MovieListPage()
        {
            InitializeComponent();
            BusyInfo = new BusyInfo();
            Filters = new MovieListFilter();
            MovieList = new ObservableCollection<Movie>();
            PagingData = new PagingData();
            PagingData.Current = 1;
            PagingData.Size = 30;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        /// <summary>
        /// 发送通知消息
        /// </summary>
        /// <param name="propetyName">属性名称字符串</param>
        protected void SendPropertyChanged(string propetyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propetyName));
            }
        }

        private void EncodeVideoClick(object sender, RoutedEventArgs e)
        {
            MovieEncodeWin win = new MovieEncodeWin();
            win.ShowDialog();
        }

        private async void Paging_LoadData(object sender, RoutedEventArgs e)
        {
            await LoadData();
        }

        private async Task LoadData()
        {
            PagingData data = await HttpInvoker.GetAsync<PagingData>("movieserver/movies?page=" + PagingData.Current + "&limit=" + PagingData.Size + "&name=" + Filters.Name);
            if (data != null)
            {
                PagingData.Size = data.Size;
                PagingData.Pages = data.Pages;
                PagingData.Total = data.Total;
                PagingData.Current = data.Current;
                MovieList = data.Records != null && data.Records.Count > 0 ? new ObservableCollection<Movie>(data.Records) : new ObservableCollection<Movie>();
            }
            pageControl.CalcPageCollection();
        }

        /// <summary>
        /// 创建剧本
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CreateMovieClick(object sender, RoutedEventArgs e)
        {
            MainWindow.ShowPage("/module/film/ui/MovieInfoPage.xaml");
        }

        private async void Page_Loaded(object sender, RoutedEventArgs e)
        {
            await LoadData();
        }

        private async void SearchClick(object sender, RoutedEventArgs e)
        {
            await LoadData();
        }

        private void DataGrid_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
            DataGrid dataGrid = sender as DataGrid;
            if(dataGrid != null)
            {
                Movie m = dataGrid.SelectedItem as Movie;
                if(m != null)
                {
                    MovieDetailPage.EditMovieId = m.Id;
                    MainWindow.ShowPage("module/film/ui/MovieDetailPage.xaml");
                }
            }
        }

        private async void DownloadMovieClick(object sender, RoutedEventArgs e)
        {
            try
            {
                if(SelectedItem == null)
                {
                    MessageBox.Show("请选择一个剧本再下载");
                    return;
                }
                if (BusyInfo.Busy)
                {
                    return;
                }
                BusyInfo.Busy = true;
                BusyInfo.BusyMessage = "查询剧本基础信息...";
                Movie movie = await HttpInvoker.GetAsync<Movie>("movieserver/movieInstances/movie/" + SelectedItem.Id);
                if (movie != null)
                {
                    BusyInfo.BusyMessage = "同步封面...";
                    //封面图，如果本地有并且不一样,那就重新下载，如果一样，那就不用下载
                    await SyncCoverFile(movie);
                    //下载剧幕
                    await SyncMovieScenes(movie);
                    BusyInfo.BusyMessage = "处理线索分组...";
                    //下载线索分组
                    await SyncClueCardGroups(movie);
                    //下载线索
                    BusyInfo.BusyMessage = "处理线索...";
                    await SyncClueCards(movie,true);
                    BusyInfo.BusyMessage = "处理电子书...";
                    List<PlayRoleBookConfig> books = await SyncPlayerRoleBook(movie);
                    //下载角色
                    BusyInfo.BusyMessage = "处理角色...";
                    await SyncPlayerRole(movie,books);
                    
                    //下载完了，更新同步结果到本地文件
                    MovieService.SaveProjectMovie(movie);
                }
            }
            finally
            {
                BusyInfo.Reset();
            }
        }

        private async void DownloadSdMovieClick(object sender, RoutedEventArgs e)
        {
            try
            {
                if (SelectedItem == null)
                {
                    MessageBox.Show("请选择一个剧本再下载");
                    return;
                }
                if (BusyInfo.Busy)
                {
                    return;
                }
                BusyInfo.Busy = true;
                BusyInfo.BusyMessage = "查询剧本基础信息...";
                Movie movie = await HttpInvoker.GetAsync<Movie>("movieserver/movieInstances/movie/" + SelectedItem.Id);
                if (movie != null)
                {
                    BusyInfo.BusyMessage = "同步封面...";
                    //封面图，如果本地有并且不一样,那就重新下载，如果一样，那就不用下载
                    await SyncCoverFile(movie);
                    //下载剧幕
                    await SyncMovieScenes(movie);
                    BusyInfo.BusyMessage = "处理线索分组...";
                    //下载线索分组
                    await SyncClueCardGroups(movie);
                    //下载线索
                    BusyInfo.BusyMessage = "处理线索...";
                    await SyncClueCards(movie, false);
                    BusyInfo.BusyMessage = "处理电子书...";
                    List<PlayRoleBookConfig> books = await SyncPlayerRoleBook(movie);
                    //下载角色
                    BusyInfo.BusyMessage = "处理角色...";
                    await SyncPlayerRole(movie, books);
                    //下载完了，更新同步结果到本地文件
                    MovieService.SaveProjectMovie(movie);
                }
            }
            finally
            {
                BusyInfo.Reset();
            }
        }

        /// <summary>
        /// 下载封面图片
        /// </summary>
        /// <param name="localMovie">本地剧本配置对象</param>
        /// <returns></returns>
        private async Task SyncCoverFile(Movie localMovie)
        {
            string digest = await HttpInvoker.GetAsync<string>("movieserver/movieInstances/movie/" + localMovie.Id + "/cover/digest");
            if (!string.IsNullOrEmpty(digest))
            {
                await DownloadFile(localMovie, "movieserver/movieInstances/movie/" + localMovie.Id + "/cover", digest, localMovie.Cover);
            }
        }

        private async Task DownloadFile(Movie localMovie,string downloadUri,string serverDigest,string reletivePath)
        {
            string rootPath = MovieService.ProjectJsonFilePath(localMovie.Id);
            string storePath = MovieService.MovieOutputFilePath(localMovie);
            await HttpInvoker.DownloadFile(downloadUri, serverDigest, reletivePath, rootPath, storePath);
        }

        private async Task SyncMovieScenes(Movie localMovie)
        {
            BusyInfo.BusyMessage = "查询剧幕列表...";
            List<SceneConfig> scenes = await HttpInvoker.GetAsync<List<SceneConfig>>("movieserver/movieSceneInstances/movie/" + localMovie.Id);
            if (scenes != null && scenes.Count > 0)
            {
                string rootPath = MovieService.ProjectJsonFilePath(localMovie.Id);
                string storePath = MovieService.MovieOutputFilePath(localMovie);
                //同步每一幕的文件
                foreach (SceneConfig sc in scenes)
                {
                    BusyInfo.BusyMessage = "处理剧幕:" + sc.Name;
                    string digest = await HttpInvoker.GetAsync<string>("movieserver/movieSceneInstances/movie/"+localMovie.Id+"/movieScene/" + sc.Id + "/digest");
                    if (!string.IsNullOrEmpty(digest))
                    {
                        await DownloadFile(localMovie, "movieserver/movieSceneInstances/movie/" + localMovie.Id + "/movieScene/" + sc.Id + "/file", digest, sc.File);
                    }
                }
                localMovie.Scenes = scenes.Select(sc =>new Scene() {
                    Name = sc.Name,
                    File = sc.File,
                    Sequence = sc.Sequence,
                    PlayMode = sc.PlayMode
                }).ToList();
            }
        }

        /// <summary>
        /// 同步线索分组
        /// </summary>
        /// <returns></returns>
        private static async Task SyncClueCardGroups(Movie localMovie)
        {
            List<ClueCardGroup> groups = await HttpInvoker.GetAsync<List<ClueCardGroup>>("movieserver/clueCardGroupInstances/movie/" + localMovie.Id);
            localMovie.ClueCardGroups = groups != null
                ? groups
                : new List<ClueCardGroup>();
        }

        private async Task SyncClueCards(Movie localMovie,bool hi)
        {
            List<ClueCardConfig> clueCards = await HttpInvoker.GetAsync<List<ClueCardConfig>>("movieserver/clueCardInstances/movie/" + localMovie.Id);
            if (clueCards == null || clueCards.Count <= 0)
            {
                return;
            }
            //同步线索文件
            foreach (ClueCardConfig clueCard in clueCards)
            {
                if (hi)
                {
                    //高清清文件
                    string digest = await HttpInvoker.GetAsync<string>("movieserver/clueCardInstances/movie/" + localMovie.Id + "/clueCard/" + clueCard.Id + "/hdDigest");
                    if (!string.IsNullOrEmpty(digest))
                    {
                        await DownloadFile(localMovie, "movieserver/clueCardInstances/movie/" + localMovie.Id + "/clueCard/" + clueCard.Id + "/hdFile", digest, clueCard.HdFile);
                    }
                }
                else
                {
                    //标清文件
                    string digest = await HttpInvoker.GetAsync<string>("movieserver/clueCardInstances/movie/" + localMovie.Id + "/clueCard/" + clueCard.Id + "/sdDigest");
                    if (!string.IsNullOrEmpty(digest))
                    {
                        await DownloadFile(localMovie, "movieserver/clueCardInstances/movie/" + localMovie.Id + "/clueCard/" + clueCard.Id + "/sdFile", digest, clueCard.SdFile);
                    }
                }
            }
            localMovie.ClueCards = clueCards.Select(clueCard => new ClueCard() {
                Id = clueCard.Id,
                Type = clueCard.Type,
                Group = clueCard.Group,
                Name = clueCard.Name,
                FilePath = hi?clueCard.HdFile:clueCard.SdFile
            }).ToList();
        }

        /// <summary>
        /// 同步角色信息
        /// </summary>
        /// <param name="localMovie"></param>
        /// <returns></returns>
        private async Task SyncPlayerRole(Movie localMovie, List<PlayRoleBookConfig> books)
        {
            List<PlayerRoleConfig> roles = await HttpInvoker.GetAsync<List<PlayerRoleConfig>>("movieserver/playRoleInstances/movie/" + localMovie.Id);
            if (roles != null && roles.Count > 0)
            {
                //同步每个角色的文件
                foreach (PlayerRoleConfig role in roles)
                {
                    string digest = await HttpInvoker.GetAsync<string>("movieserver/playRoleInstances/movie/" + localMovie.Id + "/playRole/" + role.Id + "/digest");
                    if (!string.IsNullOrEmpty(digest))
                    {
                        await DownloadFile(localMovie, "movieserver/playRoleInstances/movie/" + localMovie.Id + "/playRole/" + role.Id + "/file", digest, role.FilePath);
                    }
                    if(books != null && books.Count > 0)
                    {
                        List<PlayRoleBookConfig> roleBooks = books.Where(book => book.PlayRoleId == role.Id).ToList();
                        role.Books = roleBooks;
                    }
                }
                localMovie.Roles = roles.Select(role => new PlayerRole() {
                    Name = role.Name,
                    Gender = role.Gender,
                    CrossGender = role.CrossGender,
                    FilePath = role.FilePath,
                    Books = role.Books != null ? role.Books.Select(b => new PlayRoleBook
                    {
                        Name = b.Name,
                        Html = b.FilePath
                    }).ToList():null
                }).ToList();
            }
        }

        private async Task<List<PlayRoleBookConfig>> SyncPlayerRoleBook(Movie localMovie)
        {
            //电子书
            List<PlayRoleBookConfig> books = await HttpInvoker.GetAsync<List<PlayRoleBookConfig>>("movieserver/playRoleBookInstances/movie/" + localMovie.Id);
            if(books !=null && books.Count > 0)
            {
                //同步每个电子书文件
                foreach(PlayRoleBookConfig book in books)
                {
                    string digest = await HttpInvoker.GetAsync<string>("movieserver/playRoleBookInstances/movie/" + localMovie.Id + "/playRoleBook/" + book.Id + "/digest");
                    if (!string.IsNullOrEmpty(digest))
                    {
                        await DownloadFile(localMovie, "movieserver/playRoleBookInstances/movie/" + localMovie.Id + "/playRoleBook/" + book.Id + "/file", digest, book.FilePath);
                    }
                    //下载电子书的图片
                    List<FileVo> images = await HttpInvoker.GetAsync<List<FileVo>>("movieserver/playRoleBookImages/playRoleBook/" + book.Id);
                    if(images != null && images.Count > 0)
                    {
                        foreach(FileVo image in images)
                        {
                            //下载图片
                            digest = await HttpInvoker.GetAsync<string>("movieserver/playRoleBookImages/" + image.Id + "/digest");
                            if (!string.IsNullOrEmpty(digest))
                            {
                                await DownloadFile(localMovie, "movieserver/playRoleBookImages/" + image.Id + "/file", digest, image.FilePath);
                            }
                        }
                    }
                }
            }
            return books;
        }

        private void MenuItem_Click(object sender, RoutedEventArgs e)
        {
            ImportMovie();
        }

        private void ImportMovieClick(object sender, RoutedEventArgs e)
        {
            ImportMovie();
        }

        private void ImportMovie()
        {
            if (SelectedItem == null)
            {
                MessageBox.Show("请选择一个剧本再导入");
                return;
            }
            var dialog = new System.Windows.Forms.FolderBrowserDialog();
            var result = dialog.ShowDialog();
            if (result == System.Windows.Forms.DialogResult.OK)
            {
                var path = dialog.SelectedPath;
                ImportMoviePage.MovieFolder = path;
                ImportMoviePage.EditMovieId = selectedItem.Id;
                MainWindow.ShowPage("module/importer/ui/ImportMoviePage.xaml");
            }
        }

        private void LogoutClick(object sender, RoutedEventArgs e)
        {
            HttpInvoker.UpdateToken(null);
            LoginPage.DeleteTokenFile();
            MainWindow.ShowLoginPage();
        }

        private async void DeleteMoieClick(object sender, RoutedEventArgs e)
        {
            if (SelectedItem == null)
            {
                MessageBox.Show("请选择一个剧本再删除");
                return;
            }
            MessageBoxResult res = MessageBox.Show("是否删除" + SelectedItem.Name + ",已经发布的剧本将不能删除");
            if (res == MessageBoxResult.OK)
            {
                if(await MovieClient.DeleteMovie(selectedItem.Id))
                {
                    MessageBox.Show("删除成功");
                }
            }
        }
    }
}
